package com.boby.homecamera.service.server

import android.content.Context
import android.media.MediaCodec
import android.media.MediaFormat
import android.media.MediaRecorder
import com.boby.homecamera.config.AppConfig
import com.pedro.encoder.Frame
import com.pedro.encoder.audio.GetAudioData
import com.pedro.encoder.input.audio.GetMicrophoneData
import com.pedro.encoder.input.sources.audio.AudioSource
import com.pedro.encoder.input.sources.video.Camera2Source
import com.pedro.encoder.input.sources.video.VideoSource
import com.pedro.encoder.input.video.Camera2ApiManager
import com.pedro.encoder.video.GetVideoData
import com.boby.homecamera.helper.WriteRecordFileHelper
import com.pedro.encoder.audio.AudioEncoder
import com.pedro.encoder.input.audio.MicrophoneManager
import com.pedro.encoder.video.VideoEncoder
import java.nio.ByteBuffer

class RecordServer2 {

    var videoSource: VideoSource? = null
        private set
    var audioSource: AudioSource? = null
        private set
    private var audioEncoder: AudioEncoder? = null
    private var videoEncoder: VideoEncoder? = null
    private var microphoneManager: MicrophoneManager? = null
    private var cameraManager: Camera2ApiManager? = null
    private var audioInitialized = false
    private var writeRecordFileHelper : WriteRecordFileHelper? = null

    private var audioFormat: MediaFormat? = null
    private var videoFormat: MediaFormat? = null
    fun init(context: Context) {
        videoSource = Camera2Source(context)

        cameraManager = Camera2ApiManager(context)
        microphoneManager = MicrophoneManager(getMicrophoneData)
        audioEncoder = AudioEncoder(getAudioData)
        videoEncoder = VideoEncoder(getVideoData)
        prepareAudio(MediaRecorder.AudioSource.MIC, AppConfig.Record.RECORD_AUDIO_BITRATE,
            AppConfig.Record.RECORD_AUDIO_SAMPLE_RATE, false, false, false)
        prepareVideo(AppConfig.Record.RECORD_VIDEO_WIDTH, AppConfig.Record.RECORD_VIDEO_HEIGHT, 30, AppConfig.Record.RECORD_VIDEO_BITRATE, 2, 0, -1, -1)

    }

    fun start() {
        if (audioInitialized) microphoneManager!!.start()
    }

    fun stop() {
        if (audioInitialized) microphoneManager!!.stop()
        writeRecordFileHelper?.stop()
        writeRecordFileHelper = null
    }

    @Synchronized
    private  fun initRecord(){
        if(audioFormat == null || videoFormat == null){
            return
        }
        writeRecordFileHelper = WriteRecordFileHelper(audioFormat!!, videoFormat!!)
    }

    private val getAudioData = object : GetAudioData {
        override fun getAudioData(audioBuffer: ByteBuffer, info: MediaCodec.BufferInfo) {
            //保存录音数据到文件、或者发送到rtsp
            writeRecordFileHelper?.writeAudio(audioBuffer,info)
        }

        override fun onAudioFormat(mediaFormat: MediaFormat) {
            audioFormat = mediaFormat
            initRecord()
        }
    }

    private val getMicrophoneData: GetMicrophoneData = object : GetMicrophoneData {
        override fun inputPCMData(frame: Frame) {
            audioEncoder!!.inputPCMData(frame)
        }
    }

    private val getVideoData = object : GetVideoData {
        override fun getVideoData(videoBuffer: ByteBuffer, info: MediaCodec.BufferInfo) {
            //保存录音数据到文件、或者发送到rtsp
            writeRecordFileHelper?.writeVideo(videoBuffer, info)

        }

        override fun onVideoFormat(mediaFormat: MediaFormat) {
            videoFormat = mediaFormat
            initRecord()
        }

        override fun onVideoInfo(sps: ByteBuffer, pps: ByteBuffer?, vps: ByteBuffer?) {

        }

    }

    fun prepareAudio(
        audioSource: Int,
        bitrate: Int,
        sampleRate: Int,
        isStereo: Boolean,
        echoCanceler: Boolean,
        noiseSuppressor: Boolean
    ): Boolean {
        if (!microphoneManager!!.createMicrophone(
                audioSource,
                sampleRate,
                isStereo,
                echoCanceler,
                noiseSuppressor
            )
        ) {
            return false
        }
//        onAudioInfoImp(isStereo, sampleRate)
        audioInitialized = audioEncoder!!.prepareAudioEncoder(bitrate, sampleRate, isStereo)
        return audioInitialized
    }

    fun prepareVideo(
        width: Int, height: Int, fps: Int, bitrate: Int, iFrameInterval: Int,
        rotation: Int, profile: Int, level: Int
    ): Boolean {
//        if (onPreview && (width != previewWidth || height != previewHeight || fps != videoEncoder!!.fps || rotation != videoEncoder!!.rotation)) {
//            stopPreview()
//        }
        return videoEncoder!!.prepareVideoEncoder(
            width, height, fps, bitrate, rotation,
            iFrameInterval, com.pedro.encoder.video.FormatVideoEncoder.SURFACE, profile, level
        )
    }




}